package com.xk._01基础篇._06二叉搜索树02.tree;

import java.util.Comparator;

/**
 * @description:
 * @author: xu
 * @date: 2022/9/20 1:01
 */
public class BST<E> extends BinaryTree<E> {

    private Comparator<E> comparator;

    public BST(Comparator<E> comparator) {
        this.comparator = comparator;
    }

    public BST() {
        this(null);
    }

    public void add(E element){
        elementNotNullCheck(element);
        if (root == null) { // 添加第一个结点
            root = new Node<>(element, null);
            size++;
            return;
        }

        // 添加的不是第一个结点
        // 找到父节点
        Node<E> node = root;
        Node<E> parent = root;
        int cmp = 0;
        while (node != null){
            cmp = compare(element, node.elememt);
            parent = node;
            if (cmp < 0){
                node = node.left;
            } else if (cmp > 0) {
                node = node.right;
            } else { // 相等
                node.elememt = element;
                return;
            }
        }
        //看看插入到父节点的哪个位置
        Node<E> newNode = new Node<>(element, parent);
        if (cmp > 0) {
            parent.right = newNode;
        } else {
            parent.left = newNode;
        }
        size++;
    }

    public void remove(E element){
        remove(node(element));
    }
    private void remove(Node<E> node){
        if (node == null) return;
        size--;

        // 度为2的节点
        if (node.hasTwoChildren()){
            // 找到后继结点
            Node<E> s = successor(node);
            // 用后继结点的值覆盖将删除结点的值
            node.elememt = s.elememt;
            // 删除后继结点
            node = s;
        }

        //删除node结点（此时node的度必为1或者0）
        Node<E> replacement = node.left != null ? node.left : node.right;
        if (replacement != null){
            // node 度为 1
            // 更改子结点的parent
            replacement.parent = node.parent;
            // 更改parent的left、right的指向
            if (node.parent == null) {
                // node是度为1的根结点
                root = replacement;
            } else if (node == node.parent.left) {
                node.parent.left = replacement;
            } else {
                node.parent.right = replacement;
            }
        } else if (node.parent == null){
            // node 度为 0，node为根结点并且是叶子结点
            root = null;
        } else {
            // node是叶子结点，但不是根节点
            if (node == node.parent.left) {
                node.parent.left = null;
            } else {
                node.parent.right = null;
            }
        }
    }

    /**
     * 根据元素查找对应的结点
     * @param element
     * @return
     */
    private Node<E> node(E element){
        elementNotNullCheck(element);
        Node<E> node = root;
        while (node != null){
            int cmp = compare(element, node.elememt);
            if (cmp == 0) return node;
            else if (cmp > 0) node = node.right;
            else node = node.left;
        }
        return node;
    }

    public boolean contains(E element){
        return node(element) != null;
    }

    /**
     * @return
     *      返回值等于0，代表e1和e2相等
     *      返回值大于0，代表e1大于e2
     *      返回值小于0，代表e1小于e2
     */
    private int compare(E e1, E e2){
        if (comparator != null){
            return comparator.compare(e1, e2);
        }
        return ((Comparable<E>) e1).compareTo(e2);
    }

    private void elementNotNullCheck(E element) {
        if (element == null){
            throw new IllegalArgumentException("element must not be null");
        }
    }
}
